﻿using UnityEngine;
using System.Collections;

[ExecuteInEditMode]
[RequireComponent(typeof(MeshCollider))]
public class HCGrid : MonoBehaviour {

	
	[SerializeField]
	private int _columns = 8;
	
	[SerializeField]
	private int _rows = 8;
	
	[SerializeField]
	private float _hexaRadius = 1f;
	
	[SerializeField]
	private Transform _hexagonPrefab = null;
	
	[SerializeField]
	HCHexagonController[] _grid;
	
	[SerializeField]
	private Material _emptyMaterial = null;
	
	[SerializeField]
	private Material _blackMaterial = null;
	
	[SerializeField]
	private Material _whiteMaterial = null;
	
	[SerializeField]
	private Material _wildCardMaterial = null;
	
	[SerializeField]
	private Material _solidMaterial = null;
	
	[SerializeField]
	private Material _selectionMaterial = null;
	
	/*
	[SerializeField]
	private Transform[] _unitList;
	*/
	private HCHexagonController _prevSelection = null;
	
	InputManager _input = new InputManager(  );
	
	// prop
	public Material EmptyMaterial
	{
		get{ return _emptyMaterial; }
	}
	public Material BlackMaterial
	{
		get{ return _blackMaterial; }
	}
	public Material WhiteMaterial
	{
		get{ return _whiteMaterial; }
	}
	public Material WildCardMaterial
	{
		get{ return _wildCardMaterial; }
	}
	public Material SolidMaterial
	{
		get{ return _solidMaterial; }
	}
	
	// selecciona un tile
	public HCHexagonController Pick(float x, float y)
	{
		HCHexagonController _selectedHex = null;
		
		float it, yts, jt, xt, yt;
		
		float _s = HCHexagon.CalcSegment( _hexaRadius );
		float _h = HCHexagon.CalcHeight( _hexaRadius );
		
		it = Mathf.Floor( x /_s );
		yts = y - (it % 2) * _h * 0.5f;
		jt = Mathf.Floor( yts / _h );
		
		xt = x - it * _s;
		yt = yts - jt * _h;
		
		int i, j;
		float _threshold = _hexaRadius * Mathf.Abs( 0.5f - yt / _h );
		if( xt > _threshold )
		{
			i = (int)it;
			j = (int)jt;
		}else{
			i = (int)(it-1);
			float _deltaJ = (yt > (_h * 0.5f)) ? 1:0;
			j = (int)(jt -  i % 2 + _deltaJ);
		}
		
		if( i >= 0 && j >= 0 && i < _columns && j < _rows )
		{
			_selectedHex = _grid[ j * _columns + i ];
		}
		
		return _selectedHex;
	}
	
	void Awake()
	{
		_input.BeginTouch = BeginTouch;
		_input.MoveTouch = MoveTouch;
		_input.EndedTouch = EndTouch;

		for( int i = 0; i < _grid.Length; i++ )
		{
			if( null != _grid[i] )
				_grid[i].Neighborhood = GetNearHexagon( _grid[i] );
		}
	}
	
	void Start()
	{
	
	}
	
	void Update()
	{
		_input.Proccess();
	}
	
	
	void Select( HCHexagonController _hex )
	{
		
		Debug.Log("selected: " + _hex.Column.ToString() + ", " + _hex.Row.ToString());
		_prevSelection = _hex;
		// mostrar lugares que se pueden mover
	}
	
	void HideNavigator()
	{
		// esconder lugares donde se puede mover
		_prevSelection = null;
	}
	
	bool CanMoveTo( HCHexagonController _source, HCHexagonController _dest )
	{
		int _dc = _dest.Column - _source.Column;
		int _dr = _dest.Row - _source.Row;
		bool _odd = (_source.Column % 2 ) == 1;
		
		if( _dr == 0 )
		{
			return ( _dc == -1 || _dc == 1 );
		}	
		else if( _dr == 1 )
		{
			return _dc == 0 || (_odd && (_dc == -1 || _dc == 1));
		}
		else if( _dr == -1 )
		{
			return _dc == 0 || ( !_odd && (_dc == -1 || _dc == 1));
		}
		
		return false;
	}
	
	private bool ValidateRow( int r )
	{
		return r >= 0 && r < _rows;
	}
	
	private bool ValidateColumn( int c )
	{
		return c >= 0 && c < _columns;
	}
	
	public ArrayList GetNearHexagon( HCHexagonController _center )
	{
		int r = _center.Row;
		int c = _center.Column;
		bool _odd = false;
		int _r = 0;
		int _c = 0;
		_odd = (c % 2 ) == 1;
		
		HCHexagonController _selectedHex = null;
		ArrayList _list = new ArrayList();
		for( int i = -1; i <= 1; i++ )
		{
			_c = c + i;
			if( ValidateColumn( _c ) )
			{
				for( int j = -1; j <= 1; j++ )
				{
					_r = r + j;
					if( ValidateRow(_r) )
					{
						_selectedHex = null;
						if( 0 != i )
						{
							if( 0 != j )
							{
								if( _odd )
								{
									if( j == 1 )
									{
										_selectedHex = _grid[ _r * _columns + _c ];
									}		
								}else{
									if( j == -1 )
									{
										_selectedHex = _grid[ _r * _columns + _c ];
									}
								}	
							}else{
								_selectedHex = _grid[ _r * _columns + _c ];
							}
						}else{
							
							if( 0 != j )
							{
								_selectedHex = _grid[ _r * _columns + _c ];
							}
						}
						
						if( null != _selectedHex )
						{
							_list.Add( _selectedHex );
						}
					}
				} 
			}
		}
		
		return _list;
	}
	
	bool Swap( HCHexagonController _hex )
	{
		if( CanMoveTo( _prevSelection, _hex ) && _prevSelection.Swap( _hex ) )
		{
			/*
			Debug.Log("swap: " + _hex.Column.ToString() + ", " + _hex.Row.ToString());
			// cambiar posiciones en el array
			int _index0 = _hex.Row * this._columns + _hex.Column;
			int _index1 = _prevSelection.Row * this._columns + _prevSelection.Column;
			
			HCHexagonController _aux = _grid[_index0];
			_grid[ _index0 ] = _grid[ _index1 ];
			_grid[ _index1 ] = _aux;	
			*/
			
			//Deselect();
			_prevSelection = null;
			
			return true;
		}
		
		return false;
	}
	
	public void ShowNavigator( HCHexagonController _hex )
	{
	
	}
	
	bool BeginTouch(IMTouch _touch)
	{
		//Debug.Log("Hola Mundo!!" + _touch.position.x.ToString() + ", " + _touch.position.y.ToString() );
		
		RaycastHit _hit = new RaycastHit();
		Ray _ray = Camera.main.ScreenPointToRay( new Vector3( _touch.position.x, _touch.position.y, 0f ) );
		
		if( Physics.Raycast( _ray, out _hit ) )
		{
			HCHexagonController _currSelection = Pick( _hit.point.x - transform.position.x, _hit.point.z - transform.position.z );
			
			// marcar areas donde puede mover
			if( _currSelection )
			{
				// si no ya hay uno seleccionado
				if( null == _prevSelection )
				{
					// si el que se eligio se puede seleccionar o no ejecuto alguna funcion de seleccion
					if( _currSelection.Select() )
						_prevSelection = _currSelection;
				}else{
					// si se puede intercambiar
					_currSelection.Swap( _prevSelection );
					HideNavigator ();
				}
				
			}else{
				HideNavigator ();
			}	
		}else{
			HideNavigator ();
		}
		
		return false;
	} 
	
	bool MoveTouch(IMTouch _touch)
	{
		return true;
	} 
	
	bool EndTouch(IMTouch _touch)
	{
		return true;
	} 

	public Material GetMaterialByType( HCHexagonController.EType _typeSelected )
	{
		switch( _typeSelected )
		{
		case HCHexagonController.EType.EMPTY: return _emptyMaterial;
		case HCHexagonController.EType.BLACK: return _blackMaterial;
		case HCHexagonController.EType.WHITE: return _whiteMaterial;
		default: return null;
		}
	}

}